home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / vga / _vgawin.c < prev    next >
C/C++ Source or Header  |  1994-11-16  |  26KB  |  1,116 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _vgawin.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. #include "vga.h"
  17.  
  18. /*----------------------------------------------------------------------------*/
  19. /* event handling, window manager, etc ...                                    */
  20. /*----------------------------------------------------------------------------*/
  21.  
  22. #define BORDER_W 5
  23. #define HEADER_W 20 
  24.  
  25. VgaWindow  win_stack[16];
  26. int win_top = 0;
  27.  
  28. static int display = 0;
  29. static int mouse_installed=0;
  30. static int mouse_two_buttons=0;
  31.  
  32. static VgaWindow root_win = 0;
  33.  
  34. static int root_color = 14; // grey 
  35.  
  36. static int pointer_shape = 0;
  37. static int mouse_x = DISP_WIDTH/2;
  38. static int mouse_y = DISP_HEIGHT/2;
  39.  
  40. static int event_buffer_e = -1;
  41. static int event_buffer_val;
  42. static VgaWindow event_buffer_win;
  43.  
  44. static int last_event_e;
  45. static int last_event_val;
  46. static VgaWindow last_event_win;
  47.  
  48. static int pointer_visible = 0;
  49.  
  50. static int save_mode;
  51. static int save_lw;
  52. static int save_ls;
  53.  
  54.  
  55. static unsigned char pointer_mask[2][2][14] = { 
  56. {{0xc0,0xf0,0x7c,0x7f,0x3f,0x3f,0x1f,0x1f,0x0d,0x0c,0x00,0x00,0x00,0x00},
  57.  {0x00,0x00,0x00,0x00,0xc0,0xc0,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0c}},
  58.  
  59. {{0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x01,0x03,0x07,0x0e,0x1c,0x38,0x30},
  60.  {0x03,0x0f,0x3e,0xfe,0xfc,0xfc,0xf8,0xf8,0xb0,0x30,0x00,0x00,0x00,0x00} }
  61. };
  62.  
  63.  
  64. static void draw_pointer()
  65. {
  66.   register int x1 = mouse_x % 8;
  67.   register int x2 = 8-x1;
  68.   register int x = mouse_x/8;
  69.   VIDEO_PTR start = VIDEO + LINE_BYTES*mouse_y + x;
  70.   register VIDEO_PTR q;
  71.   register unsigned char c;
  72.  
  73.   set_color(black);
  74.  
  75.   if (pointer_shape == 1)
  76.   { pixel(root_win->id,mouse_x-2,mouse_y);
  77.     pixel(root_win->id,mouse_x-1,mouse_y);
  78.     pixel(root_win->id,mouse_x,mouse_y);
  79.     pixel(root_win->id,mouse_x+1,mouse_y);
  80.     pixel(root_win->id,mouse_x+3,mouse_y);
  81.     pixel(root_win->id,mouse_x,mouse_y-2);
  82.     pixel(root_win->id,mouse_x,mouse_y-1);
  83.     pixel(root_win->id,mouse_x,mouse_y+1);
  84.     pixel(root_win->id,mouse_x,mouse_y+2);
  85.     circle(root_win->id,mouse_x,mouse_y,6);
  86.     return;
  87.    }
  88.  
  89.  
  90.   int a = 0;
  91.   int b = 14;
  92.   int d = 1;
  93.   int k = 0;
  94.  
  95.   if (mouse_y + 15 > DISP_MAX_Y) 
  96.   { a = 13;
  97.     b = -1;
  98.     d = -1;
  99.     start -= 14*LINE_BYTES;
  100.    }
  101.  
  102.   if (x > 77) 
  103.   { start -= 2;
  104.     k = 1;
  105.    }
  106.  
  107.   port_out(8, GRA_I);
  108.  
  109.   for(int i=a; i!=b; i+=d)
  110.   { q = start;
  111.     c = (pointer_mask[k][0][i]>>x1);
  112.     port_out(c, GRA_D);
  113.     *q = *q;
  114.     ++q; 
  115.     c = ((pointer_mask[k][1][i]>>x1) | (pointer_mask[k][0][i]<<x2));
  116.     port_out(c, GRA_D);
  117.     *q = *q;
  118.     
  119.     if (x2)
  120.     { ++q;
  121.       c = (pointer_mask[k][1][i]<<x2);
  122.       port_out(c, GRA_D);
  123.       *q = *q;
  124.      }
  125.     start+=LINE_BYTES;
  126.    }
  127. }
  128.  
  129. static void show_pointer()
  130. { if (!pointer_visible) draw_pointer(); 
  131.   pointer_visible = 1;
  132.  }
  133.  
  134. static void hide_pointer()
  135. { if (pointer_visible) draw_pointer(); 
  136.   pointer_visible = 0;
  137.  }
  138.  
  139.  
  140. static void set_pointer_shape(int shape)
  141. { if (pointer_shape != shape) 
  142.   { draw_pointer();
  143.     pointer_shape = shape;
  144.     draw_pointer();
  145.   }
  146.  }
  147.  
  148.  
  149. static void save_box(VgaWindow win)
  150. { register int y;
  151.   register VIDEO_PTR p;
  152.   register VIDEO_PTR q;
  153.   register VIDEO_PTR first;
  154.   register VIDEO_PTR last;
  155.  
  156.   if (win_top <= 1) { win->plane[0] = 0; return; }
  157.  
  158.   int left   = win->x0;
  159.   int top    = win->y0;
  160.   int right  = win->x1;
  161.   int bottom = win->y1;
  162.  
  163.   int i,l,r;
  164.  
  165.   if(left < 0) left = 0;
  166.   if(top  < 0) top = 0;
  167.   if(right  > DISP_MAX_X) right = DISP_MAX_X;
  168.   if(bottom > DISP_MAX_Y) bottom = DISP_MAX_Y;
  169.  
  170.   l = (left>>3);
  171.   r = (right>>3);
  172.  
  173.   win->plane[0] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  174.   win->plane[1] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  175.   win->plane[2] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  176.   win->plane[3] = (VIDEO_PTR)malloc((r-l+1)*(bottom-top+1));
  177.  
  178.   /* set read mode 0 */
  179.   port_out(5, GRA_I);
  180.   port_out(0, GRA_D);
  181.  
  182.   /* read planes 0 to 3 */
  183.   for(i=0; i<4; i++)
  184.   { p = win->plane[i];
  185.  
  186.     port_out(4, GRA_I);
  187.     port_out(i, GRA_D);
  188.  
  189.     first = VIDEO + LINE_BYTES*top + l;
  190.     last  = VIDEO + LINE_BYTES*top + r;
  191.  
  192.     for(y=top; y<=bottom; y++)
  193.     { for(q=first; q<=last; q++) *p++ = *q;
  194.       first  += LINE_BYTES;
  195.       last   += LINE_BYTES;
  196.      }
  197.   }
  198. }
  199.  
  200.  
  201.  
  202. static void restore_box(VgaWindow win, int left, int top, int right, int bottom)
  203. { register int y;
  204.   register VIDEO_PTR p;
  205.   register VIDEO_PTR q;
  206.   register VIDEO_PTR first;
  207.   register VIDEO_PTR last;
  208.   int save_mode;
  209.   int save_col;
  210.   int i;
  211.  
  212.   if(left < 0) left = 0;
  213.   if(top  < 0) top = 0;
  214.   if(right  > DISP_MAX_X) right = DISP_MAX_X;
  215.   if(bottom > DISP_MAX_Y) bottom = DISP_MAX_Y;
  216.  
  217.   save_mode = set_mode(0);
  218.  
  219.   if (win->plane[0])
  220.      save_col = set_color(0);
  221.   else
  222.      save_col = set_color(root_color);
  223.  
  224.  
  225.   // clean area
  226.  
  227.   port_out(8, GRA_I);
  228.   port_out(0xFF, GRA_D);
  229.   first  = VIDEO + LINE_BYTES*top + left/8;
  230.   last   = VIDEO + LINE_BYTES*top + right/8;
  231.   for(y=top; y<=bottom; y++)
  232.   { for(q=first; q<=last; q++) *q = *q;
  233.     first  += LINE_BYTES;
  234.     last   += LINE_BYTES;
  235.    }
  236.  
  237.  
  238.   // fill in plane data
  239.  
  240.   set_mode(2); /* or */
  241.  
  242.   if (win->plane[0])
  243.     for(i = 0; i < 4; i++)
  244.     {
  245.       p = win->plane[i];
  246.   
  247.       set_color(1<<i);
  248.   
  249.       first  = VIDEO + LINE_BYTES*top + left/8;
  250.       last   = VIDEO + LINE_BYTES*top + right/8;
  251.   
  252.       port_out(8, GRA_I);
  253.   
  254.       for(y=top; y<=bottom; y++)
  255.       { for(q=first; q<=last; q++,p++) 
  256.         { port_out(*p, GRA_D);
  257.           *q = *q;
  258.          }
  259.         first  += LINE_BYTES;
  260.         last   += LINE_BYTES;
  261.        }
  262.   
  263.       free((char*)win->plane[i]);
  264.     }
  265.   
  266.     set_mode(save_mode);
  267.     set_color(save_col);
  268. }
  269.  
  270.  
  271. static void put_header(VgaWindow win)
  272. { char str[80];
  273.   int n = (win->width - 40)/text_width("H");
  274.   strncpy(str,win->header,n);
  275.   str[n] = 0;
  276.   put_ctext(root_win->id,win->x0 + win->width/2 + 20, win->y0 + 10 ,str,0);
  277.  }
  278.  
  279. static void set_header(VgaWindow win, const char* s)
  280. { int save_co = set_color(win->label_col);
  281.   int save_mo = set_mode(0);
  282.   put_header(win);
  283.   if (s != win->header) strcpy(win->header,s);
  284.   set_color(1);
  285.   put_header(win);
  286.   set_color(save_co);
  287.   set_mode(save_mo);
  288.  }
  289.  
  290. void set_header(Window win, const char* s) { set_header(win_stack[win],s); }
  291.  
  292.  
  293.  
  294. static void draw_window(VgaWindow win)
  295. {
  296.   int bw  = win->xpos - win->x0 - 2;
  297.   int lw  = win->ypos - win->y0 - 2;
  298.   int bw1 = 2*(bw+1);
  299.  
  300.   int x0 = win->x0;
  301.   int y0 = win->y0;
  302.  
  303.   int x1 = win->x1;
  304.   int y1 = win->y1;
  305.  
  306.   int save_mode = set_mode(0);
  307.  
  308.   set_color(win->bg_col);
  309.   box(root_win->id,x0,y0,x1,y1);
  310.   set_color(win->label_col);
  311.   box(root_win->id,x0+bw,y0+bw,x1-bw,y0+lw);
  312.   box(root_win->id,x0,y0+bw1,x0+bw,y1-bw1);
  313.   box(root_win->id,x1-bw,y0+bw1,x1,y1-bw1);
  314.   box(root_win->id,x0+bw1,y1-bw,x1-bw1,y1);
  315.   box(root_win->id,x0+bw1,y0,x1-bw1,y0+bw);
  316.   set_color(1);
  317.  
  318.   rectangle(root_win->id,x0,y0,x1,y1);
  319.  
  320.   line(root_win->id,x0+bw,y0+bw,x0+bw1,y0+bw);
  321.   line(root_win->id,x0+bw1,y0+bw,x0+bw1,y0+1);
  322.   line(root_win->id,x0+bw1,y0+1,x1-bw1,y0+1);
  323.   line(root_win->id,x1-bw1,y0+1,x1-bw1,y0+bw);
  324.   line(root_win->id,x1-bw1,y0+bw,x1-bw,y0+bw);
  325.   line(root_win->id,x1-bw,y0+bw,x1-bw,y0+bw1);
  326.   line(root_win->id,x1-bw,y0+bw1,x1-1,y0+bw1);
  327.   line(root_win->id,x1-1,y0+bw1,x1-1,y1-bw1);
  328.   line(root_win->id,x1-1,y1-bw1,x1-bw,y1-bw1);
  329.   line(root_win->id,x1-bw,y1-bw1,x1-bw,y1-bw);
  330.   line(root_win->id,x1-bw,y1-bw,x1-bw1,y1-bw);
  331.   line(root_win->id,x1-bw1,y1-bw,x1-bw1,y1-1);
  332.   line(root_win->id,x1-bw1,y1-1,x0+bw1,y1-1);
  333.   line(root_win->id,x0+bw1,y1-1,x0+bw1,y1-bw);
  334.   line(root_win->id,x0+bw1,y1-bw,x0+bw,y1-bw);
  335.   line(root_win->id,x0+bw,y1-bw,x0+bw,y1-bw1);
  336.   line(root_win->id,x0+bw,y1-bw1,x0+1,y1-bw1);
  337.   line(root_win->id,x0+1,y1-bw1,x0+1,y0+bw1);
  338.   line(root_win->id,x0+1,y0+bw1,x0+bw,y0+bw1);
  339.   line(root_win->id,x0+bw,y0+bw1,x0+bw,y0+bw);
  340.  
  341.   rectangle(root_win->id, win->xpos-1, win->ypos-1,
  342.                       win->xpos+win->width, win->ypos+win->height);
  343.  
  344.   // iconize-button
  345.   set_color(0);
  346.   box(root_win->id,x0+13,y0+3,x0+27,y0+15);
  347.   set_color(1);
  348.   rectangle(root_win->id,x0+13,y0+3,x0+27,y0+15);
  349.   line(root_win->id,x0+14,y0+16,x0+28,y0+16);
  350.   line(root_win->id,x0+28,y0+4,x0+28,y0+15);
  351.   line(root_win->id,x0+17,y0+6,x0+23,y0+6);
  352.   line(root_win->id,x0+16,y0+6,x0+20,y0+13);
  353.   line(root_win->id,x0+17,y0+6,x0+20,y0+13);
  354.   line(root_win->id,x0+24,y0+6,x0+20,y0+13);
  355.   line(root_win->id,x0+23,y0+6,x0+20,y0+13);
  356.  
  357.   set_header(win->id,win->header);
  358.  
  359.   set_mode(save_mode);
  360.  
  361. }
  362.  
  363.  
  364. Window open_window(int x,int y,int width,int height,const char* header,
  365.                                                     const char* label)
  366.   VgaWindow win = new vga_window;
  367.  
  368.   win_stack[++win_top] = win;
  369.   win->id = win_top;
  370.  
  371.   strcpy(win->header," ");
  372.   strcpy(win->label,label);
  373.  
  374.   if ( strcmp(label,"PANEL") == 0)
  375.      { win->bg_col = white; // grey
  376.        win->label_col = violet;
  377.       }
  378.   else
  379.      { win->bg_col = white;
  380.        win->label_col = yellow;
  381.       }
  382.  
  383.   width  += 2*BORDER_W;
  384.   height += HEADER_W+BORDER_W;
  385.  
  386.   if (width > DISP_WIDTH) width = DISP_WIDTH;
  387.   if (height > DISP_HEIGHT) height = DISP_HEIGHT;
  388.  
  389.   if (x+width > DISP_WIDTH) x = DISP_WIDTH - width;
  390.   if (x < 0) x = 0;
  391.   if (y+height > DISP_HEIGHT) y = DISP_HEIGHT - height;
  392.   if (y < 0) y = 0;
  393.  
  394.   win->x0 = x;
  395.   win->y0 = y;
  396.   win->x1 = x+width-1;
  397.   win->y1 = y+height-1;
  398.   win->xpos = x+BORDER_W;
  399.   win->ypos = y+HEADER_W;
  400.   win->width = width - 2*BORDER_W; 
  401.   win->height = height - HEADER_W - BORDER_W;
  402.  
  403.   win->iconized = 0;
  404.   win->save_x0 = 3;
  405.   win->save_y0 = 3 + 150*(win_top-1);
  406.   win->save_x1 = win->save_x0 + 128 + 2*BORDER_W;
  407.   win->save_y1 = win->save_y0 + 128 + HEADER_W + BORDER_W;
  408.   win->save_bg_col = white;
  409.  
  410.   save_box(win);
  411.   draw_window(win);
  412.   set_header(win->id,header);
  413.   return win->id;
  414. }
  415.  
  416.  
  417. void close_window(Window w)
  418. { VgaWindow win = win_stack[win_top];  /* can close top window only */
  419.   restore_box(win,win->x0,win->y0,win->x1,win->y1);
  420.   win_top--;
  421.   delete win;
  422.  }
  423.  
  424.  
  425.  
  426.  
  427.  
  428. void set_read_gc()
  429. { save_mode = set_mode(1);
  430.   save_ls   = set_line_style(0);
  431.   save_lw   = set_line_width(1);
  432.   set_color(1);
  433.   show_pointer();
  434.  }
  435.  
  436. void reset_gc()
  437. { hide_pointer();
  438.   set_mode(save_mode);
  439.   set_line_style(save_ls);
  440.   set_line_width(save_lw);
  441.  }
  442.  
  443.  
  444. #define UP  72
  445. #define DO  80
  446. #define LE  75
  447. #define RI  77
  448.  
  449. #define F1  59
  450. #define F2  60
  451. #define F3  61
  452. #define F4  62
  453. #define SF1 84
  454. #define SF2 85
  455. #define SF3 86
  456. #define CF1 94
  457. #define CF2 95
  458. #define CF3 96
  459.  
  460. static int handle_next_event(Window* win, int *val, int *x, int *y)
  461. {
  462.   int  e =  no_event;
  463.   int  i;
  464.   VgaWindow w;
  465.  
  466.   union REGS key_regs;
  467.   union REGS mouse_regs;
  468.  
  469.   if (event_buffer_e != -1)
  470.   { *val = event_buffer_val;
  471.     w = event_buffer_win;
  472.     *win = w->id;
  473.     *x = mouse_x - w->xpos;
  474.     *y = mouse_y - w->ypos;
  475.     last_event_e = event_buffer_e;
  476.     last_event_val = event_buffer_val;
  477.     last_event_win = event_buffer_win;
  478.     event_buffer_e = -1;
  479.     return last_event_e;
  480.    }
  481.  
  482.   mouse_regs.x.cx = 8*mouse_x;
  483.   mouse_regs.x.dx = 8*mouse_y;
  484.  
  485.   if (kbhit())
  486.   { 
  487.     char c = getch();
  488.  
  489.     int step = 8;
  490.  
  491.     if (c==27) 
  492.     { close_display();
  493.       exit(0);
  494.      }
  495.  
  496.     if (c != 0)   /* ascii char */
  497.        { *val = c;
  498.          e = key_press_event;
  499.         }
  500.     else          /* cursor or function key  */
  501.        { 
  502.          c = getch();
  503.  
  504.          switch(c) {
  505.  
  506.          case  LE: mouse_regs.x.cx -= step;
  507.                    e = motion_event;
  508.                    break;
  509.  
  510.          case  RI: mouse_regs.x.cx += step;
  511.                    e = motion_event;
  512.                    break;
  513.  
  514.          case  UP: mouse_regs.x.dx -= step;
  515.                    e = motion_event;
  516.                    break;
  517.  
  518.          case  DO: mouse_regs.x.dx += step;
  519.                    e = motion_event;
  520.                    break;
  521.  
  522.          case  F1: *val = 1;
  523.                    e = button_press_event;
  524.                    break;
  525.  
  526.          case  F2: *val = 2;
  527.                    e = button_press_event;
  528.                    break;
  529.  
  530.          case  F3: *val = 3;
  531.                    e = button_press_event;
  532.                    break;
  533.  
  534.          case  F4: *val = 1;
  535.                    e = button_release_event;
  536.                    break;
  537.  
  538.          case SF1: *val = -1;
  539.                    e = button_press_event;
  540.                    break;
  541.  
  542.          case SF2: *val = -2;
  543.                    e = button_press_event;
  544.                    break;
  545.  
  546.          case SF3: *val = -3;
  547.                    e = button_press_event;
  548.                    break;
  549.  
  550.          case CF1: *val = 4;
  551.                    e = button_press_event;
  552.                    break;
  553.  
  554.          case CF2: *val = 5;
  555.                    e = button_press_event;
  556.                    break;
  557.  
  558.          case  CF3: *val = 6;
  559.                    e = button_press_event;
  560.                    break;
  561.         }
  562.  
  563.         /* set cursor position */
  564.         mouse_regs.x.ax=04;
  565.         int86(0x33,&mouse_regs,&mouse_regs);
  566.       }
  567.  
  568.    } /* kbhit */
  569.  
  570.  else
  571.  
  572.   if (mouse_installed)
  573.   { 
  574.     int but;
  575.  
  576.     /* check for button press and release events */
  577.  
  578. //INT 33 - MS MOUSE - RETURN BUTTON PRESS DATA
  579. //    AX = 0005h
  580. //    BX = button
  581. //        0000h left
  582. //        0001h right
  583. //        0002h middle (Mouse Systems/Logitech mouse)
  584. //Return: AX = 1 if button pressed
  585. //      BX = number of times specified button has been pressed since last call
  586. //      CX = column at time specified button was last pressed
  587. //      DX = row at time specified button was last pressed
  588.  
  589. //INT 33 - MS MOUSE - RETURN BUTTON RELEASE DATA
  590. //    AX = 0006h
  591. //    BX = button
  592. //        0000h left
  593. //        0001h right
  594. //        0002h middle (Mouse Systems/Logitech mouse)
  595. //Return: AX = 1 if button released
  596. //      BX = # of times specified button has been released since last call
  597. //      CX = column at time specified button was last released
  598. //      DX = row at time specified button was last released
  599.  
  600.     for(but=0; but < 3; but++)
  601.     { 
  602.       mouse_regs.x.ax=5;
  603.       mouse_regs.x.bx=but;
  604.       int86(0x33,&mouse_regs,&mouse_regs);
  605.  
  606.       if (mouse_regs.x.bx)
  607.       { e = button_press_event;
  608.         break;
  609.        }
  610.  
  611.       mouse_regs.x.ax=6;
  612.       mouse_regs.x.bx=but;
  613.       int86(0x33,&mouse_regs,&mouse_regs);
  614.  
  615.       if (mouse_regs.x.bx)
  616.       { e = button_release_event;
  617.         break;
  618.        }
  619.  
  620.      }
  621.  
  622.  
  623.     if (but < 3) 
  624.     { 
  625.       if (but == 0) *val = 1;   // left
  626.       if (but == 1) *val = 3;   // right
  627.  
  628.       //INT 16 - GET KEYBOARD SHIFT KEY STATES
  629.       //          AH = 0002h
  630.       //  OUTPUT: AL  bit 0    right shift
  631.       //              bit 1    left shift
  632.       //              bit 2    ctrl
  633.       //              bit 3    alt
  634.  
  635.       key_regs.h.ah=0x02;
  636.       int86(0x16,&key_regs,&key_regs);
  637.  
  638.       // ALT key simulates middle button  (two-button mouse)
  639.       if (key_regs.h.al & 8) *val = 2; 
  640.  
  641.       if (key_regs.h.al & 3) *val = -*val;   /* shift */
  642.       if (key_regs.h.al & 4) *val += 3;      /* ctrl  */
  643.      }
  644.  
  645.    // INT 33 MS-MOUSE GET CURSOR POSITION
  646.    mouse_regs.x.ax=03;
  647.    int86(0x33,&mouse_regs,&mouse_regs);
  648.   }
  649.  
  650.   if (mouse_regs.x.cx/8 != mouse_x || mouse_regs.x.dx/8 != mouse_y)
  651.   { if (e==no_event) e = motion_event;
  652.     draw_pointer();
  653.     mouse_y = mouse_regs.x.dx/8;
  654.     mouse_x = mouse_regs.x.cx/8;
  655.     draw_pointer();
  656.    }
  657.  
  658.   for(i = win_top; i >= 0; i--)
  659.   { w = win_stack[i];
  660.     if (mouse_x >= w->x0  && mouse_x <= w->x1 &&
  661.         mouse_y >= w->y0  && mouse_y <= w->y1 )  break;
  662.    }
  663.  
  664.   *win = w->id;
  665.   *x = mouse_x - w->xpos;
  666.   *y = mouse_y - w->ypos;
  667.  
  668.   if (e != no_event)
  669.   { last_event_e   = e;
  670.     last_event_val = *val;
  671.     last_event_win = w;
  672.    }
  673.  
  674.   return e;
  675.  }
  676.  
  677.  
  678. void put_back_event() 
  679. { event_buffer_e   = last_event_e;  
  680.   event_buffer_val = last_event_val; 
  681.   event_buffer_win = last_event_win; 
  682.  }
  683.  
  684. static void change_geometry(VgaWindow win, int x0, int y0, int x1, int y1)
  685. {
  686.   if (x0==win->x0 && y0==win->y0 && x1==win->x1 && y1==win->y1) return;
  687.  
  688.   int w = x1-x0+1;
  689.   int h = y1-y0+1;
  690.  
  691.   draw_pointer();
  692.   restore_box(win,win->x0,win->y0,win->x1,win->y1);
  693.  
  694.   win->x0 = x0;
  695.   win->y0 = y0;
  696.   win->x1 = x1;
  697.   win->y1 = y1;
  698.   win->xpos = x0+BORDER_W;
  699.   win->ypos = y0+HEADER_W;
  700.   win->width = w - 2*BORDER_W; 
  701.   win->height = h - HEADER_W - BORDER_W;
  702.  
  703.   save_box(win);
  704.   draw_window(win);
  705.   draw_pointer();
  706. }
  707.  
  708.  
  709. static void iconize(VgaWindow win)
  710. { Window w;
  711.   int val,x,y;
  712.   box(root_win->id,win->x0+14,win->y0+4,win->x0+26,win->y0+14);
  713.   while (handle_next_event(&w,&val,&x,&y) != button_release_event);
  714.   box(root_win->id,win->x0+14,win->y0+4,win->x0+26,win->y0+14);
  715.  
  716.   int x0 = win->save_x0;
  717.   int y0 = win->save_y0;
  718.   int x1 = win->save_x1;
  719.   int y1 = win->save_y1;
  720.   int bg = win->save_bg_col;
  721.   win->save_x0 = win->x0;
  722.   win->save_y0 = win->y0;
  723.   win->save_x1 = win->x1;
  724.   win->save_y1 = win->y1;
  725.   win->save_bg_col = win->bg_col;
  726.   win->bg_col =  bg;
  727.   change_geometry(win,x0,y0,x1,y1);
  728.   win->iconized = 1-win->iconized;
  729.  
  730.   if (win->iconized) 
  731.      insert_bitmap(win->id, leda_icon_width, leda_icon_height, leda_icon_bits);
  732.  }
  733.  
  734. static void move_win(VgaWindow win, int *x, int *y)
  735. { int xp0 = win->x0;
  736.   int yp0 = win->y0;
  737.   int xp1 = win->x1;
  738.   int yp1 = win->y1;
  739.   int wi  = xp1-xp0+1;
  740.   int he  = yp1-yp0+1;
  741.   int xb  = win->xpos - xp0;
  742.   int yb  = win->ypos - yp0;
  743.   int xc = mouse_x; /* absolute cursor coordinates */
  744.   int yc = mouse_y; 
  745.   int dx = xc-xp0;  /* relative to upper left corner */
  746.   int dy = yc-yp0;
  747.  
  748.   Window w;
  749.   int e,val;
  750.  
  751.   rectangle(root_win->id,xp0-1,yp0-1,xp1+1,yp1+1);
  752.  
  753.   do { e = handle_next_event(&w,&val,x,y);
  754.       if (mouse_x != xc || mouse_y != yc)
  755.        { int rx0 = mouse_x-dx-1;
  756.          int ry0 = mouse_y-dy-1;
  757.          int rx1 = mouse_x-dx+wi;
  758.          int ry1 = mouse_y-dy+he;
  759.          rectangle(root_win->id,rx0,ry0,rx1,ry1);
  760.          rectangle(root_win->id,xc-dx-1,yc-dy-1,xc-dx+wi,yc-dy+he);
  761.          xc = mouse_x;
  762.          yc = mouse_y;
  763.        }
  764.      } while (e != button_release_event);
  765.  
  766.   xc -= dx;
  767.   yc -= dy;
  768.  
  769.   rectangle(root_win->id,xc-1,yc-1,xc+wi,yc+he);
  770.  
  771.   if (xc < 0) xc = 0;
  772.   if (yc < 0) yc = 0;
  773.   if (xc + wi > DISP_MAX_X) xc = DISP_MAX_X - wi;
  774.   if (yc + he > DISP_MAX_Y) yc = DISP_MAX_Y - he;
  775.  
  776.   if (win_top > 1)  /* move panel */
  777.   { change_geometry(win,xc,yc,xc+wi-1,yc+he-1);
  778.     if (win->iconized) 
  779.        insert_bitmap(win->id, leda_icon_width, leda_icon_height, leda_icon_bits);
  780.     return;
  781.    }
  782.  
  783.   xc -= xc % 8;
  784.   xc += xp0 % 8;
  785.  
  786.   draw_pointer();
  787.   copy_rect(root_win->id,xp0,yp0+1,xp0+wi,yp0+he-1,xc,yc+1);
  788.   draw_pointer();
  789.  
  790.   set_mode(0);
  791.   set_color(root_color);
  792.  
  793.   if (xc > xp0) 
  794.      box(root_win->id,xp0,yp0,xc-1,yp1);
  795.   else
  796.      box(root_win->id,xc+wi,yp0,xp1,yp1);
  797.  
  798.   if (yc > yp0) 
  799.      box(root_win->id,xp0,yp0,xp1,yc-1);
  800.   else
  801.      box(root_win->id,xp0,yc+he,xp1,yp1);
  802.  
  803.   set_color(1);
  804.   rectangle(root_win->id,xc,yc,xc+wi-1,yc+he-1);
  805.  
  806.   set_mode(1);
  807.  
  808.   win->x0 = xc; 
  809.   win->y0 = yc; 
  810.   win->x1 = xc+wi-1; 
  811.   win->y1 = yc+he-1; 
  812.   win->xpos = xc+xb; 
  813.   win->ypos = yc+yb; 
  814.  
  815. }
  816.  
  817.  
  818. static void resize_win(VgaWindow win, int* x, int* y, int pos)
  819. { int xp0 = win->x0;
  820.   int yp0 = win->y0;
  821.   int xp1 = win->x1;
  822.   int yp1 = win->y1;
  823.   int xb  = win->xpos - xp0;
  824.   int yb  = win->ypos - yp0;
  825.   
  826.   int xc  = mouse_x; /* absolute cursor coordinates */
  827.   int yc  = mouse_y;
  828.  
  829.   Window w;
  830.   int e,val,dx,dy;
  831.  
  832.   rectangle(root_win->id,xp0-1,yp0-1,xp1+1,yp1+1);
  833.  
  834.   switch(pos) {
  835.   
  836.    case 0: dx = xp0-xc;          /* upper left */
  837.            dy = yp0-yc;
  838.            break;
  839.  
  840.    case 1: dx = xp1-xc;          /* upper right */
  841.            dy = yp0-yc;
  842.            break;
  843.  
  844.    case 2: dx = xp1-xc;          /* lower right */
  845.            dy = yp1-yc;
  846.            break;
  847.  
  848.    case 3: dx = xp0-xc;          /* lower left */
  849.            dy = yp1-yc;
  850.            break;
  851.  
  852.    }
  853.  
  854.   do { e = handle_next_event(&w,&val,x,y);
  855.        if (mouse_x != xc || mouse_y != yc)
  856.         { 
  857.           switch(pos) {
  858.  
  859.           case 0: rectangle(root_win->id,mouse_x+dx-1,mouse_y+dy-1,xp1+1,yp1+1);
  860.                   rectangle(root_win->id,xc+dx-1,yc+dy-1,xp1+1,yp1+1);
  861.                   break;
  862.           
  863.           case 1: rectangle(root_win->id,xp0-1,mouse_y+dy-1,mouse_x+dx+1,yp1+1);
  864.                   rectangle(root_win->id,xp0-1,yc+dy-1,xc+dx+1,yp1+1);
  865.                   break;
  866.  
  867.           case 2: rectangle(root_win->id,xp0-1,yp0-1,mouse_x+dx+1,mouse_y+dy+1);
  868.                   rectangle(root_win->id,xp0-1,yp0-1,xc+dx+1,yc+dy+1);
  869.                   break;
  870.              
  871.           case 3: rectangle(root_win->id,mouse_x+dx-1,yp0-1,xp1+1,mouse_y+dy+1);
  872.                   rectangle(root_win->id,xc+dx-1,yp0-1,xp1+1,yc+dy+1);
  873.                   break;
  874.           
  875.            }
  876.  
  877.           xc = mouse_x;
  878.           yc = mouse_y;
  879.         }
  880.      } while (e != button_release_event);
  881.  
  882.    xc += dx;
  883.    yc += dy;
  884.  
  885.    switch(pos) {
  886.  
  887.    case 0: win->x0 = xc; 
  888.            win->y0 = yc; 
  889.            break;
  890.                 
  891.    case 1: win->x1 = xc; 
  892.            win->y0 = yc; 
  893.            break;
  894.               
  895.    case 2: win->x1 = xc; 
  896.            win->y1 = yc; 
  897.            break;
  898.  
  899.    case 3: win->x0 = xc; 
  900.            win->y1 = yc; 
  901.            break;
  902.            
  903.    }
  904.  
  905.   win->xpos = win->x0 + xb;
  906.   win->ypos = win->y0 + yb;
  907.   win->width  = win->x1 - win->x0 - 2*xb + 1; 
  908.   win->height = win->y1 - win->y0 - xb - yb + 1; 
  909.  
  910.   rectangle(root_win->id,win->x0-1,win->y0-1,win->x1+1,win->y1+1);
  911.  
  912.   draw_pointer();
  913.  
  914.   restore_box(win,xp0,yp0,xp1,yp1);
  915.  
  916.   save_box(win);
  917.  
  918.   draw_window(win);
  919.  
  920.   draw_pointer();
  921.  
  922.   *x = win->width;
  923.   *y = win->height;
  924.  
  925. }
  926.  
  927.  
  928. int check_next_event(Window* w, int* val, int* x, int *y, unsigned long* t)
  929. {
  930.   // non-blocking
  931.   
  932.   // a primitive window manager active while searching for next event
  933.  
  934.   int cx[4];
  935.   int cy[4];
  936.   int bw = BORDER_W;
  937.   int lw = HEADER_W;
  938.  
  939.   int e = handle_next_event(w,val,x,y);
  940.  
  941.   VgaWindow win = win_stack[*w];
  942.  
  943.   int x0 = win->x0;
  944.   int y0 = win->y0;
  945.   int x1 = win->x1;
  946.   int y1 = win->y1;
  947.  
  948.  
  949.   cx[0] = x0;
  950.   cy[0] = y0;
  951.   cx[1] = x1-6;
  952.   cy[1] = y0;
  953.   cx[2] = x1-6;
  954.   cy[2] = y1-6;
  955.   cx[3] = x0;
  956.   cy[3] = y1-6;
  957.  
  958.   if ( (x0 <= mouse_x && mouse_x <= x0+bw) 
  959.     || (x1 >= mouse_x && mouse_x >= x1-bw)
  960.     || (y0 <= mouse_y && mouse_y <= y0+lw)
  961.     || (y1 >= mouse_y && mouse_y >= y1-bw))
  962.     {
  963.       // pointer on window boundary: move or resize window
  964.  
  965.      if (win != win_stack[win_top])  /* only top window can be changed  */
  966.      { set_pointer_shape(0);
  967.        return no_event;
  968.       }
  969.  
  970.      for(int i=0; i<4; i++)
  971.        if ( cy[i] <= mouse_y && mouse_y <= cy[i]+6 &&
  972.             cx[i] <= mouse_x && mouse_x <= cx[i]+6 )
  973.        { set_pointer_shape(1);
  974.          if (e == button_press_event && ! win->iconized) 
  975.          { if (win->iconized)
  976.              e = no_event;
  977.            else
  978.              resize_win(win,x,y,i);
  979.            e = configure_event;
  980.           }
  981.           return e;
  982.         }
  983.  
  984.     set_pointer_shape(0);
  985.    
  986.     if (x0+13 <= mouse_x && mouse_x <= x0+27 &&
  987.         y0+3  <= mouse_y && mouse_y <= y0+15 && e == button_press_event)
  988.     { iconize(win);
  989.       return (win->iconized) ? no_event : configure_event;
  990.      }
  991.  
  992.  
  993.     if (e== button_press_event) 
  994.     { move_win(win,x,y);
  995.       if (win_top==1 || win->iconized)  
  996.          return handle_next_event(w,val,x,y);  
  997.       else
  998.          return configure_event;
  999.      }
  1000.  
  1001.     e = no_event;
  1002.  
  1003.   }  // if pointer on window boundary
  1004.  
  1005.   set_pointer_shape(0);
  1006.  
  1007.   return e;
  1008. }
  1009.  
  1010.  
  1011. int get_next_event(Window* win, int* val, int* x, int *y, unsigned long* t)
  1012. { // blocking
  1013.   int e = no_event;
  1014.   while (e == no_event) e = check_next_event(win,val,x,y,t);
  1015.   return e;
  1016.  }
  1017.  
  1018.  
  1019.  
  1020. void open_display()
  1021. { REGS regs;
  1022.  
  1023.   if (display) return;
  1024.  
  1025.   display = 1;
  1026.  
  1027.   vga_init(1,root_color);
  1028.  
  1029.   //INT 33 - MS MOUSE - RESET DRIVER AND READ STATUS
  1030.   //    AX = 0000h
  1031.   //Return: AX = status
  1032.   //        0000h hardware/driver not installed
  1033.   //        FFFFh hardware/driver installed
  1034.   //        BX = number of buttons
  1035.   //        FFFFh two buttons
  1036.   //        0000h other than two
  1037.   //        0003h Mouse Systems/Logitech mouse
  1038.   regs.x.ax=0x00;
  1039.   int86(0x33,®s,®s);
  1040.   mouse_installed = (regs.x.ax == 0x0ffff);
  1041.   mouse_two_buttons = (regs.x.bx == 0x0ffff);
  1042.  
  1043.   //INT 33 - MS MOUSE - DEFINE HORIZONTAL CURSOR RANGE = 0..DISP_MAX_X
  1044.   regs.x.ax=0x07;
  1045.   regs.x.cx=0;
  1046.   regs.x.dx=8*DISP_MAX_X;
  1047.   int86(0x33,®s,®s);
  1048.  
  1049.   //INT 33 - MS MOUSE - DEFINE VERTICAL CURSOR RANGE = 0..DISP_MAX_Y
  1050.   regs.x.ax=0x08;
  1051.   regs.x.cx=0;
  1052.   regs.x.dx=8*DISP_MAX_Y;
  1053.   int86(0x33,®s,®s);
  1054.  
  1055.   //INT 33 - MS MOUSE - DEFINE MICKEY/PIXEL RATIO = 1
  1056.   regs.x.ax=0x0F;
  1057.   regs.x.cx=1;
  1058.   regs.x.dx=1;
  1059.   int86(0x33,®s,®s);
  1060.  
  1061.   //INT 33 - MS MOUSE - SET CURSOR POSITION
  1062.   mouse_x = DISP_MAX_X/2;
  1063.   mouse_y = DISP_MAX_Y/2;
  1064.   regs.x.cx = 8*mouse_x;
  1065.   regs.x.dx = 8*mouse_y;
  1066.   regs.x.ax=04;
  1067.   int86(0x33,®s,®s);
  1068.  
  1069.   root_win = new vga_window;
  1070.   root_win->id = 0;
  1071.   win_stack[0] = root_win;
  1072.   win_top = 0;
  1073.  
  1074.   root_win->x0 = -1000;
  1075.   root_win->y0 = -1000;
  1076.   root_win->x1 =  1000;
  1077.   root_win->y1 =  1000;
  1078.   root_win->xpos = 0;
  1079.   root_win->ypos = 0;
  1080.   root_win->width = DISP_WIDTH;
  1081.   root_win->height = DISP_HEIGHT;
  1082.   root_win->bg_col = root_color;
  1083.  
  1084.   set_color(root_color);
  1085.   box(root_win->id,0,0,DISP_MAX_X,DISP_MAX_Y);
  1086.   set_color(black);
  1087.   //insert_bitmap(root_win,w,h,leda_bits);
  1088. }
  1089.  
  1090.  
  1091.  
  1092. void close_display()
  1093. { union REGS regs;
  1094.   vga_init(0,0);
  1095.   regs.h.ah=0x00;
  1096.   regs.h.al=0x02;
  1097.   int86(0x10,®s,®s);
  1098.   delete root_win;
  1099. }
  1100.  
  1101.  
  1102. int  display_width() { return DISP_WIDTH; }
  1103. int  display_height(){ return DISP_HEIGHT; }
  1104. int  display_depth() { return DISP_DEPTH; }
  1105.  
  1106. int  window_width(Window win)  { return win_stack[win]->width; }
  1107. int  window_height(Window win) { return win_stack[win]->height; }
  1108.  
  1109. void window_position(Window win,int* x,int* y) 
  1110. { *x = win_stack[win]->x0; 
  1111.   *y = win_stack[win]->y0; 
  1112.  }
  1113.  
  1114.